import time
from os import waitpid

from playwright.async_api import Page
from playwright.sync_api import expect
from common.base_page import BasePage
from locators.agileEmergency.emergencyPlanMgr.planTextMgr.loc_plan_text_list import LocPlanTextList
from locators.agileEmergency.emergencyPlanMgr.planTextMgr.loc_plan_text_add import LocPlanTextAdd
from locators.agileEmergency.emergencyPlanMgr.planTextMgr.loc_plan_text_detail import LocPlanTextDetail
from locators.agileEmergency.emergencyPlanMgr.planTextMgr.loc_plan_text_assess import LocPlanTextAssess
from locators.agileEmergency.emergencyPlanMgr.planTextMgr.loc_plan_text_edit import LocPlanTextEdit
from common.logger import logger


class PagePlanText(BasePage):
    def __init__(self, page: Page):
        super().__init__(page)
        self.switch_menu('敏捷应急')
        self.page.locator('div.title:has-text("应急预案统计")').wait_for(state="visible", timeout=15000)
        self.switch_menu('预案文本管理')

        # 初始化字段映射
        self.FIELD_MAPPING = {
            # 属性定位器映射，用于新增、编辑、查看
            'name': LocPlanTextAdd.loc_name,
            'publish_number': LocPlanTextAdd.loc_publish_number,
            'org_dept_id': LocPlanTextAdd.loc_org_dept_id,
            'unit_code': LocPlanTextAdd.loc_unit_code,
            'phone': LocPlanTextAdd.loc_phone,
            'area_code': LocPlanTextAdd.loc_area_code,
            'level': LocPlanTextAdd.loc_level,
            'type': LocPlanTextAdd.loc_type,
            'upper_plans': LocPlanTextAdd.loc_upper_plans,
            'link_plans': LocPlanTextAdd.loc_link_plans,
            'incident_type': LocPlanTextAdd.loc_incident_type,
            'implementation_time': LocPlanTextAdd.loc_implementation_time,
            'publish_time': LocPlanTextAdd.loc_publish_time,
            'publish_org_id': LocPlanTextAdd.loc_publish_org_id,
            'evaluation_cycle': LocPlanTextAdd.loc_evaluation_cycle,
            'electronic_plan': LocPlanTextAdd.loc_electronic_plan,

            # 评估字段，评估需要修订才可以编辑删除
            'evaluation_time': LocPlanTextAssess.loc_evaluation_time,
            'evaluation_opinion': LocPlanTextAssess.loc_evaluation_opinion,
            'attachment': LocPlanTextAssess.loc_attachment,

            # 查询条件定位器映射，用于查询
            'search_name': LocPlanTextList.loc_search_name,
            'search_publish_org_id': LocPlanTextList.loc_search_publish_org_id,
            'search_type': LocPlanTextList.loc_search_type,
            'search_level': LocPlanTextList.loc_search_level,
            'search_revision_status': LocPlanTextList.loc_search_revision_status,
            'search_evaluation_status': LocPlanTextList.loc_search_evaluation_status,
            'search_publish_time': LocPlanTextList.loc_search_publish_time,
        }
        # 特殊字段类型
        self.SELECT_FIELDS = {'org_dept_id', 'area_code', 'level', 'type', 'upper_plans', 'link_plans', 'incident_type', 'publish_org_id', 'evaluation_cycle',
                              'search_type', 'search_level', 'search_revision_status', 'search_evaluation_status',
                              'evaluation_opinion'}
        self.DATE_FIELDS = {'implementation_time', 'publish_time',
                            'search_publish_time',
                            'evaluation_time'}
        self.FILE_FIELDS = {'electronic_plan', 'attachment'}

    @BasePage.register_special_field('name')
    def handle_name(self, field, value, locator, locator_class, clear_fields):
        # 自动带出，不可编辑。测试数据有值，但不做表单操作，只用作验证
        pass

    @BasePage.register_special_field('area_code')
    def handle_area_code(self, field, value, locator, locator_class, clear_fields):
        self.select_single_tree(locator, value, level_flag=True)

    @BasePage.register_special_field('electronic_plan')
    def handle_electronic_plan(self, field, value, locator, locator_class, clear_fields):
        if clear_fields:
            self.click(locator_class.loc_remove)
        self.upload_file(file_path=value, loc=locator)
        # 预案名称，根据上传的文件名自动带出
        self.wait_for_field_autofill(locator_class.loc_name)

        # 等待文件上传完成，出现预览按钮
        self.get_locator_by_role(locator_class.loc_preview).wait_for(state="visible", timeout=15000)
        time.sleep(3)

    @BasePage.register_special_field('attachment')
    def handle_attachment(self, field, value, locator, locator_class, clear_fields):
        if clear_fields:
            self.click(locator_class.loc_remove)
        self.upload_file(file_path=value, loc=locator)

        # 等待文件上传完成，出现预览按钮
        self.get_locator_by_role(locator_class.loc_preview).wait_for(state="visible", timeout=15000)

    @BasePage.register_special_field('search_publish_time')
    def handle_search_publish_time(self, field, value, locator, locator_class, clear_fields):
        self.fill_date_time(locator, value[0], value[1])

    def add_plan_text(self, data: dict,
                      wait_success: bool = True, screenshot: bool = False, cancel: bool = False):
        """
        新增

        参数说明:
        - data: 包含数据的字典，键为字段名，值为字段值
        - wait_success: 是否等待保存成功提示，默认为True
        - screenshot: 是否在操作前截图，默认为False
        - cancel: 是否点击取消，默认为False
        """

        # 点击新增按钮
        logger.info('点击新增按钮')
        self.click(LocPlanTextList.loc_add)

        logger.info('填写表单')
        self.fill_form(LocPlanTextAdd, data)

        if cancel:
            # 取消操作
            logger.info('点击取消，不新增数据')
            self.click(LocPlanTextAdd.loc_cancel)
        else:
            # 提交表单,附件上传成功后不能立即点击，增加重试次数
            logger.info('点击确定按钮保存数据')

            self.click(LocPlanTextAdd.loc_sure)

            # 等待操作完成
            if wait_success:
                self.wait_for_message("操作成功")

        if screenshot:
            self.take_screenshot("新增提交后")

        return self

    def search_plan_text(self, data: dict, screenshot: bool = False):
        """
        查询

        参数说明:
        - data: 包含数据的查询条件字典，键为字段名，值为字段值
        - screenshot: 是否操作截图，默认为False
        """

        logger.info('查询列表')

        logger.info('输入查询条件')
        self.fill_form(LocPlanTextList, data)

        logger.info('点击查询')
        self.click(LocPlanTextList.loc_search)

        if screenshot:
            self.take_screenshot("查询结果")

        return self

    def assess_plan_text(self, search_name: str, data: dict,
                         wait_success: bool = True, screenshot: bool = False, cancel: bool = False):
        """
        评估

        参数说明:
        - search_name: 查询字段，搜索编辑目标数据。尽量是精准查询出唯一值。
        - data: 包含数据的字典，键为字段名，值为字段值
        - wait_success: 是否等待保存成功提示，默认为True
        - screenshot: 是否在操作前截图，默认为False
        - cancel: 是否点击取消，默认为False
        """

        logger.info('找到要编辑的数据')
        self.fill(LocPlanTextList.loc_search_name, search_name)
        self.click(LocPlanTextList.loc_search)
        self.page.get_by_text("共 1 条").wait_for(state="visible", timeout=15000)

        logger.info('点击评估按钮')
        self.click(LocPlanTextList.loc_assess)
        logger.info('填写表单')
        self.fill_form(LocPlanTextAssess, data)

        if cancel:
            # 取消操作
            logger.info('点击取消，不新增数据')
            self.click(LocPlanTextAssess.loc_cancel)
        else:
            # 提交表单
            logger.info('点击确定按钮保存数据')
            self.click(LocPlanTextAssess.loc_sure)

            # 等待操作完成
            if wait_success:
                self.wait_for_message("操作成功")

        if screenshot:
            self.take_screenshot("新增提交后")

        return self

    def edit_plan_text(self, search_name: str, data: dict,
                   wait_success: bool = True, screenshot: bool = False, cancel: bool = False):
        """
        编辑

        参数说明:
        - search_name: 查询字段，搜索编辑目标数据。尽量是精准查询出唯一值。
        - data: 包含数据的字典，键为字段名，值为字段值
        - wait_success: 是否等待保存成功提示，默认为True
        - screenshot: 是否在操作前截图，默认为False
        - cancel: 是否点击取消，默认为False
        """

        logger.info('找到要编辑的数据')
        self.fill(LocPlanTextList.loc_search_name, search_name)
        self.click(LocPlanTextList.loc_search)
        self.page.get_by_text("共 1 条").wait_for(state="visible", timeout=15000)

        logger.info('点击修订按钮')
        self.click(LocPlanTextList.loc_edit)

        # 编辑字段
        logger.info('编辑表单')
        self.fill_form(LocPlanTextEdit, data, clear_fields=True)

        if cancel:
            # 取消操作
            logger.info('点击取消，不保存编辑的数据')
            self.click(LocPlanTextEdit.loc_cancel)
        else:
            # 提交表单
            logger.info('点击确定保存编辑的信息')
            self.click(LocPlanTextEdit.loc_sure)

            # 等待操作完成
            if wait_success:
                self.wait_for_message("操作成功")

        if screenshot:
            self.take_screenshot("编辑提交后")

        return self

    def detail_plan_text(self, search_name: str, data: dict,
                     screenshot: bool = False):
        """
        查看

        参数说明:
        - search_name: 查询字段，搜索查看目标数据。尽量是精准查询出唯一值。
        - data: 包含数据的字典，键为字段名，值为字段值
        - screenshot: 是否在操作前截图，默认为False
        """

        # 点击查看按钮
        logger.info('找到要查看的数据')
        self.fill(LocPlanTextList.loc_search_name, search_name)
        self.click(LocPlanTextList.loc_search)
        self.page.get_by_text("共 1 条").wait_for(state="visible", timeout=15000)

        logger.info('点击查看按钮')
        self.click(LocPlanTextList.loc_detail)

        logger.info('查看并验证数据')

        # 验证每个字段
        for field, expected_value in data.items():
            if expected_value is None or expected_value == "":
                continue

            locator = getattr(LocPlanTextDetail, f"loc_{field}", None)
            if not locator:
                logger.warning(f"未找到字段 '{field}' 的定位器，跳过验证")
                continue

            # 附件字段，跳过查看验证
            if field in self.FILE_FIELDS:
                continue

            actual_value = self.get_loc_value(locator)
            assert actual_value == expected_value, (
                f"字段 [{field}] 验证失败: 期望值 '{expected_value}', 实际值 '{actual_value}'"
            )
            logger.info(f"字段 [{field}] 验证通过: {expected_value}")

        if screenshot:
            self.take_screenshot("查看截图")

        # 关闭详情页
        self.click(LocPlanTextDetail.loc_close)

        return self

    def delete_plan_text(self, search_name: str,
                     wait_success: bool = True, screenshot: bool = False, cancel: bool = False):
        """
        删除

        参数说明:
        - search_name: 查询字段，搜索要删除的目标数据。尽量是精准查询出唯一值。
        - wait_success: 是否等待保存成功提示，默认为True
        - screenshot: 是否在操作前截图，默认为False
        - cancel: 是否点击取消，默认为False
        """

        # 勾选要删除的数据，点击删除按钮
        self.fill(LocPlanTextList.loc_search_name, search_name)
        self.click(LocPlanTextList.loc_search)
        self.page.get_by_text("共 1 条").wait_for(state="visible", timeout=15000)

        logger.info('通过关键字找到数据行，并勾选对应行')
        self.select_row_checkbox(target_value=search_name)
        logger.info('点击删除按钮')
        self.click(LocPlanTextList.loc_delete)

        if cancel:
            # 取消操作
            logger.info('点击取消，不删除勾选的数据')
            self.click(LocPlanTextList.loc_cancel)
        else:
            # 确定删除
            logger.info('点击确定删除勾选的数据')
            self.click(LocPlanTextList.loc_sure)

            # 等待操作完成
            if wait_success:
                self.wait_for_message("操作成功")

        if screenshot:
            self.take_screenshot("删除后截图")